package algocity.modelo.juego;

import algocity.modelo.azar.AzarReal;
import algocity.modelo.azar.FuncionAzar;
import algocity.modelo.catastrofe.*;
import algocity.modelo.mapa.Mapa;
import algocity.modelo.mapa.Operador;

import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashSet;

public class MinisterioDeClima
        extends Deregistrador<Catastrofe,String>
        implements Trabajable<ObjetoNulo>, Registrable<Catastrofe,String>, RegistrableError, Serializable {

    private final FuncionAzar azar;
    private Mapa mapa;
    private LlamadorMaestro<String,String> llamadorError;
    private Collection<Operador<Catastrofe>> registroDiferido;

    public MinisterioDeClima(FuncionAzar azar, Mapa mapa) {
        this.azar = azar;
        this.mapa = mapa;
        llamadorError = new LlamadorMaestro<String,String>();
        registroDiferido = new LinkedHashSet<Operador<Catastrofe>>();
    }

    @Override
    public Boolean trabajar(ObjetoNulo parametro) {
        Catastrofe catastrofe = null;
        if ( azar.nuevoValor((float) 0.0, (float) 1.0) < Parametros.PROBABILIDAD_CATASTROFE) {
                catastrofe = azar.nuevoBoolean()  ? crearGodzilla()
                                                : new Terremoto(mapa, mapa.hectareaAlAzar());
        } else {
            return Boolean.TRUE;
        }

        try {
            for ( Operador<Catastrofe> operador : registroDiferido ) {
                catastrofe.registrar(operador);
            }
            catastrofe.hacerDanio();
        } catch (Throwable e) {
            llamadorError.llamar(e.getLocalizedMessage());
        }

        return Boolean.TRUE;
    }

    private Catastrofe crearGodzilla() {
        final float queGodzillaElegimosHoy = azar.nuevoValor((float) 0.0, (float) 1.0);
        if ( queGodzillaElegimosHoy < (float) 0.3 ) {
            return new GodzillaLineal(mapa, new AzarReal());
        } else if ( queGodzillaElegimosHoy < (float) 0.6 ) {
            return new GodzillaZigZag(mapa, new AzarReal());
        } else {
            return new GodzillaDiagonal(mapa, new AzarReal());
        }
    }

    @Override
    public void registrar(Operador<Catastrofe> observador) {
        this.registroDiferido.add(observador);
    }

    @Override
    public Collection<Operador<String>> deregistrarError()
    {
        return llamadorError.deregistrar();
    }

    @Override
    public void deregistrarError(Operador<String> observador)
    {
        llamadorError.deregistrarError(observador);
    }

    @Override
    public void registrarAvisoError(Operador<String> observador) {
        llamadorError.registrar(observador);
    }

    @Override
    protected Collection<Operador<Catastrofe>> getObservadores()
    {
        return registroDiferido;
    }
}
